package com.chinaunicom.emergency.interceptor;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.chinaunicom.emergency.annotation.Permission;
import com.chinaunicom.emergency.util.ConfigUtil;
import com.chinaunicom.emergency.util.HttpUtil;
import com.chinaunicom.emergency.util.IpUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @author liliang
 * @date 2019-12-13
 */
@Log4j2
@Component
public class PermissionInterceptor implements HandlerInterceptor {


    //给 RestTemplate 实例添加 @LoadBalanced 注解，开启 @LoadBalanced 与 Ribbon 的集成
    //需要RestTemplate的地方引入@LoadBalanced@Bean
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI().replaceFirst(request.getContextPath(), "");
        String authorization = request.getHeader("Authorization");
        String deviceIp = IpUtil.getIpAddr(request);
        if (authorization == null) {
            authorization = request.getParameter("Authorization");
        }

        JSONObject returnData = null;
        if (authorization != null && authorization.toUpperCase().startsWith("BEARER ")) {
            String token = authorization.substring(7);


//            // 获取 servlet上下文
//            ServletContext sc = request.getSession().getServletContext();
//            // 获取 spring 容器
//            AbstractApplicationContext cxt = (AbstractApplicationContext) WebApplicationContextUtils.getWebApplicationContext(sc);
//            EurekaDiscoveryClient discoveryClient = (EurekaDiscoveryClient)cxt.getBean("discoveryClient");
//            Random random = new Random();
//            List<ServiceInstance> sList = discoveryClient.getInstances("oauth-user");
//            if(sList.size() == 0){
//                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
//                returnJson(response,"权限校验失败，未发现认证服务 , url:"+uri);
//                return false;
//            }
//            ServiceInstance authApp = sList.get(random.nextInt(sList.size()));
//            String url = authApp.getUri().toString();
//            Map<String, String> headPara = new HashMap<>();
//            headPara.put("x-forwarded-for", deviceIp);
//            JSONObject jsonBody = new JSONObject();
//
//            String returnMessage = HttpClient.postHtmlData(url+ "/oauth/check_token?" +
//                    "token=" + token, jsonBody.toJSONString(), headPara);
////            log.info(returnMessage);

            MultiValueMap<String, Object> headers = new LinkedMultiValueMap<String, Object>();
            HttpEntity requests = new HttpEntity(new JSONObject().toJSONString(), headers);

            String returnMessage = restTemplate.postForObject("http://jt-oauth/oauth/check_token?token="+token,requests,String.class);
            returnData = JSONObject.parseObject(returnMessage);
            if (returnData.get("active") != null && returnData.get("active").equals(true)) {
                String userName = returnData.getString("user_name");
                log.info("token对应的用户：" + userName);
                request.setAttribute("userName", userName);
            }
        }
        //访问跟目录或带有点符号的资源不做权限校验
        String temp = ConfigUtil.get("system.pass.url");
        temp = temp + "/verification|/login|/druid|/swagger|/v2|/actuator/|/oauth";
        String[] urls = temp.split("\\|");
        for (String url : urls) {
            if (uri.indexOf(url) != -1) {
                return true;
            }
        }
        if ("/".equals(uri) || uri.indexOf(".") != -1) {
            return true;
        }
        boolean pass = true;


        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        Permission permissionsAnno;
        try{
            permissionsAnno = method.getAnnotation(Permission.class);
            if(permissionsAnno == null){
                log.info("该权限在代码中未注解，直接放过：" + uri);
                return true;
            }
        }catch (Exception e){
            log.info("该权限在代码中未注解，直接放过：" + uri,e);
            return true;
        }
        if (returnData == null) {
            (response).sendError(HttpServletResponse.SC_UNAUTHORIZED, "访问被拒绝，请提供请求头 Authorization");
            HttpUtil.returnJson(response,"访问被拒绝，请提供请求头 Authorization , url:"+uri);
            return false;
        } else {
            //截取token
            try {
                if (returnData.get("active") != null && returnData.get("active").equals(true)) {
                    //校验权限。。
                    JSONArray authorities = returnData.getJSONArray("authorities");
                    if (authorities == null || authorities.isEmpty()) {
                        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                        HttpUtil.returnJson(response,"没有访问该接口的权限 , url:"+uri);
                        pass = false;
                    } else {
                        String permission = permissionsAnno.value();
                        log.info("请求权限为：" + permission);
                        String clientId = returnData.getString("client_id");
                        for(int a = 0 ;a < authorities.size(); a++ ){
                            JSONObject authJson = JSONObject.parseObject((String) authorities.get(a));
//                            JSONObject authJson1 = authorities.getJSONObject(a);
                            JSONArray authArr = new JSONArray();
                            if(clientId.equals("yjglweb")){
                                authArr = authJson.getJSONArray("web");
                            }else if(clientId.equals("yjglapp")){
                                authArr = authJson.getJSONArray("app");
                            }else{
                                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                                HttpUtil.returnJson(response,"该clientId未识别:"+clientId);
                                return false;
                            }

                            if (authArr == null || !authArr.contains(permission)) {
                                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                                HttpUtil.returnJson(response,"没有访问该接口的权限 , url:"+uri + ", code=" + permission);
                                pass = false;
                            }
                            request.setAttribute("permission",authArr);
                        }

                    }
                } else {
                    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                    HttpUtil.returnJson(response,"访问被拒绝，Authorization token过期");
                    pass = false;
                }
            } catch (Exception e) {
                log.error("token校验异常",e);
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                HttpUtil.returnJson(response,"访问被拒绝，校验token失败");
                pass = false;
            }
        }
        return pass;
    }


}
